use bytes::Bytes;

use crate::{connection::Connection, db::Db, frame::Frame, parse::Parse, Result};

#[derive(Debug)]
pub struct Set {
    key: String,
    value: Bytes,
}

impl Set {
    pub fn new(key: impl ToString, value: Bytes) -> Self {
        Self {
            key: key.to_string(),
            value,
        }
    }

    pub fn key(&self) -> &str {
        &self.key
    }

    pub fn value(&self) -> &Bytes {
        &self.value
    }

    pub fn parse_frames(parse: &mut Parse) -> Result<Self> {
        let key = parse.next_string()?;
        let value = parse.next_bytes()?;

        Ok(Self { key, value })
    }

    pub fn into_frame(self) -> Frame {
        let mut frame = Frame::array();
        frame.push_bulk(Bytes::from("set".as_bytes()));
        frame.push_bulk(Bytes::from(self.key.into_bytes()));
        frame.push_bulk(self.value);
        frame
    }

    pub async fn apply(self, db: &Db, dst: &mut Connection) -> Result<()> {
        db.set(self.key, self.value);

        let response = &Frame::Simple("OK".into());

        debug!("{:?}", response);

        dst.write_frame(response).await?;

        Ok(())
    }
}
